package com.ld.admin.util.permission.impl;

import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.jsoup.nodes.Element;

import com.ld.admin.config.SystemStaticParams;
import com.ld.admin.model.system.SysMenuModel;
import com.ld.admin.model.system.SysRoleModel;
import com.ld.admin.plugin.cache.PermCacheUtil;
import com.ld.admin.plugin.cache.UrlPermCacheUtil;
import com.ld.admin.util.PermissionUtil;
import com.ld.admin.util.permission.PermissionChecker;
import com.ld.shieldsb.common.core.util.StringUtils;
import com.ld.shieldsb.common.web.util.Web;

/**
 * 系统用户权限实现【所有的权限检查都在该类中，可以用其他实现替换该类】
 * 
 * @author <a href="mailto:donggongai@126.com" target="_blank">吕凯</a>
 * @date 2020年9月21日 下午3:23:35
 *
 */
public class SysUserPermChecker implements PermissionChecker {
    @Override
    public boolean checkPermission(HttpServletRequest request) {
        Long userId = Web.Util.getSessionUserId(request);
        return userId == null || !userId.equals(SystemStaticParams.TOP_MANAGER_ID); // 非顶级管理员，顶级管理员不判断权限
    }

    @Override
    public String getUrlPerm(String url) {
        return UrlPermCacheUtil.getUrlPerm(url);
    }

    /**
     * 获取url对应的权限model
     * 
     * @Title getPermModleByUrl
     * @author 吕凯
     * @date 2019年6月11日 下午2:03:21
     * @param url
     * @return SysMenuModel
     */
    @Override
    public SysMenuModel getPermModleByUrl(String url) {
        return UrlPermCacheUtil.getPermModleByUrl(url);
    }

    /**
     * 根据pageId获取权限model
     * 
     * @Title getPermByPageId
     * @author 吕凯
     * @date 2019年6月19日 下午4:24:55
     * @param pageId
     * @return SysMenuModel
     */
    @Override
    public SysMenuModel getPermByPageId(String pageId) {
        return PermCacheUtil.getPermByPageId(pageId);
    }

    /**
     * 从session中获取用户的所有角色id
     * 
     * @Title getUserPermSubjects
     * @author 吕凯
     * @date 2019年4月13日 上午8:55:54
     * @param session
     * @return Set<String>
     */
    @Override
    @SuppressWarnings("unchecked")
    public Set<String> getUserPermSubjects(HttpSession session) {
        Set<String> userRolenames = (Set<String>) session.getAttribute(SystemStaticParams.SESSION_USER_ROLENAMES);
        return userRolenames;
    }

    /**
     * 从request中获取session中保存的所有权限id
     * 
     * @Title getUserPermSubjects
     * @author 吕凯
     * @date 2019年9月21日 上午9:19:02
     * @param request
     * @return Set<String>
     */
    @Override
    public Set<String> getUserPermSubjects(HttpServletRequest request) {
        HttpSession session = request.getSession();
        return getUserPermSubjects(session);
    }

    /**
     * 获取pageId或dataUrl对应的权限对象
     * 
     * @Title getPermModel
     * @author 吕凯
     * @date 2019年9月21日 上午9:04:20
     * @param pageId
     * @param dataUrl
     * @return SysMenuModel
     */
    @Override
    public SysMenuModel getPermModel(String pageId, String dataUrl) {
        boolean hasPageId = false;
        if (StringUtils.isNotBlank(pageId)) {
            hasPageId = true;
        }
        SysMenuModel childPermModle = null;
        if (hasPageId) {
            childPermModle = PermissionUtil.getPermByPageId(pageId); // 存在pageId对应的权限
        } else {
            childPermModle = PermissionUtil.getPermModleByUrl(dataUrl); // 获取url在权限中的映射（前提是不同权限的url唯一）
        }
        return childPermModle;
    }

    @Override
    public boolean checkPerm(HttpServletRequest request, String pageId, String dataUrl) {
        SysMenuModel childPermModle = getPermModel(pageId, dataUrl);

        return checkPerm(request, childPermModle);
    }

    @Override
    public boolean checkPerm(HttpServletRequest request, SysMenuModel permModle) {
        Set<String> userRoleNames = getUserPermSubjects(request);
        if (permModle != null && SystemStaticParams.PERMISSION_NO != permModle.getPermType()) { // 未设置属性不判断权限且权限管理中有
            List<String> permRoleNames = permModle.getPermRoles().stream().map(SysRoleModel::getName).collect(Collectors.toList());
            if (SystemStaticParams.PERMISSION_LOGIN_NO_CHECK == permModle.getPermType()) { // 登录权限（登录后即可使用的权限）
                if (Web.Util.getSessionUserId(request) == null) { // 未登录
                    return false;
                }
            } else if (SystemStaticParams.PERMISSION_CHECK == permModle.getPermType()) {
                List<String> names = userRoleNames
                        .stream().map(ur -> permRoleNames.stream()
                                .filter(pr -> Objects.nonNull(ur) && Objects.nonNull(pr) && Objects.equals(ur, pr)).findAny().orElse(null))
                        .filter(Objects::nonNull).collect(Collectors.toList());

                if (names.size() == 0) {// 无匹配角色则无权限
                    return false;
                }
            }
        }

        return true;
    }

    /**
     * 检查ele元素是否存在某权限
     * 
     * @Title checkElePerm
     * @author 吕凯
     * @date 2019年9月21日 上午8:58:33
     * @param request
     * @param userPermIds
     * @param childEle
     * @param pageId
     *            pageId属性值，对应权限表中的pageId，唯一
     * @param dataUrl
     *            链接地址，可能不唯一
     * @return boolean
     */
    @Override
    public boolean checkElePerm(HttpServletRequest request, Element childEle, String pageId, String dataUrl) {
        if (!childEle.hasAttr("noperm")) { // 未设置属性不判断权限
            SysMenuModel childPermModle = getPermModel(pageId, dataUrl);

            if (childEle.hasAttr("unionAdd")) { // 联合权限，与后面的权限验证必须同时满足
                if (childEle.attr("unionAdd").equals("false")) {
                    return false;
                }
                if (childPermModle == null) {
                    return false;
                }
            } else if (childEle.hasAttr("unionOr")) { // 联合权限，与后面的权限验证满足一个即可
                if (childEle.attr("unionOr").equals("true")) {
                    return true;
                }
                if (childPermModle == null) {
                    return false;
                }

            }
            return checkPerm(request, pageId, dataUrl);
        }
        return true;
    }

}
